package br.ufpe.cin.if680.lightmirror.core;

public class Vetor {
	protected double x;
	protected double y;
	protected double z;
	
	public Vetor(double x, double y, double z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	public double getX() {
		return x;
	}
	
	public double getY() {
		return y;
	}
	
	public double getZ() {
		return z;
	}

	/**
	 * Normaliza este vetor.
	 */
	public void normalizar() {
		double norma = this.getNorma();
		this.setX(this.getX()/norma);
		this.setY(this.getY()/norma);
		this.setZ(this.getZ()/norma);
	}
	
	/**
	 * Retorna a norma do vetor.
	 * @return
	 */
	public double getNorma(){
		return Math.sqrt(this.produtoInterno(this));
	}
	
	/**
	 * Retorna um componente ortogonal deste vetor em relação a v.
	 * @param v
	 * @return
	 */
	public Vetor ortogonal(Vetor v){
		//XXX fiz isso aki so pra V e N nunca conhecidirem, pq da merda qd isso acontesse pois o vetor resultande eh (000)
		if(this.getX() == v.getX() && this.getY() == v.getZ() && this.getZ() == v.getZ()){
			this.setZ(this.getZ() + 1);
		}
		return this.subtracao(this.projecao(v));
	}
	
	/**
	 * Retorna um vetor formado pelo produto dos componentes deste vetor e de v.
	 * @param v
	 * @return
	 */
	public Vetor produtoComponentes(Vetor v) {
		return new Vetor(this.getX()*v.getX(), this.getY()*v.getY(), this.getZ()*v.getZ());
	}
	
	/**
	 * Retorna o produto escalar com a constante c.
	 * @param c
	 * @return
	 */
	public Vetor produtoEscalar(double c) {
		return new Vetor(this.getX()*c, this.getY()*c, this.getZ()*c);
	}
	
	/**
	 * Retorna o produto interno com o vetor v.
	 * @param v
	 * @return
	 */
	public double produtoInterno(Vetor v) {
		return this.getX() * v.getX() + this.getY() * v.getY() + this.getZ() * v.getZ();
	}
	
	/**
	 * Retorna o produto vetorial deste vetor com v.
	 * @param v
	 * @return
	 */
	public Vetor produtoVetorial(Vetor v) {
		double x = this.getY() * v.getZ() - this.getZ() * v.getY();
		double y = this.getZ() * v.getX() - this.getX() * v.getZ();
		double z = this.getX() * v.getY() - this.getY() * v.getX();
		return new Vetor(x,y,z);
	}
	
	/**
	 * Retorna a projeção deste vetor em v.
	 * @param v
	 * @return
	 */
	public Vetor projecao(Vetor v){
		double c = produtoInterno(v)/(v.produtoInterno(v));
		return v.produtoEscalar(c);
	}
	
	public void setX(double x) {
		this.x = x;
	}
	
	public void setY(double y) {
		this.y = y;
	}
	
	public void setZ(double z) {
		this.z = z;
	}
	
	/**
	 * Retorna a soma deste vetor com v.
	 * @param v
	 * @return
	 */
	public Vetor soma(Vetor v){
		return new Vetor(this.getX() + v.getX(), this.getY() + v.getY(), this.getZ() + v.getZ());
	}
	
	/**
	 * Retorna a subtração deste valor com v.
	 * @param v
	 * @return
	 */
	public Vetor subtracao(Vetor v) {
		return new Vetor(this.getX() - v.getX(),this.getY() - v.getY(), this.getZ() - v.getZ());
	}
}
